package com.harriague.calculadora.business;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.harriague.calculadora.dao.SesionRepository;
import com.harriague.calculadora.model.Calculo;
import com.harriague.calculadora.model.Sesion;

import de.congrace.exp4j.Calculable;
import de.congrace.exp4j.ExpressionBuilder;
import de.congrace.exp4j.UnknownFunctionException;
import de.congrace.exp4j.UnparsableExpressionException;

@Service
public class CalculoService {

	@Autowired
	SesionRepository sesionRepository;

	private Map<String, List<Calculo>> buffer = new HashMap<String, List<Calculo>>();

	/**
	 * Persists in a new session all the operations made by an specified user
	 * @param user
	 * @param name
	 * @throws IllegalArgumentException
	 */
	@Transactional
	public void save(String user, String name) throws IllegalArgumentException {
		if (findByUserAndName(user, name) == null) {
			Sesion sesion = new Sesion();
			sesion.setName(name);
			sesion.setUser(user);
			sesion.setCalculos(buffer.get(user));
			sesionRepository.save(sesion);
			buffer.remove(user);
		} else {
			throw new IllegalArgumentException(
					"Ya existe una sesion con ese nombre para ese usuario");
		}
	}

	@Transactional
	public Sesion findById(Long id) {
		return sesionRepository.findOne(id);
	}

	@Transactional
	public Sesion findByName(String name) {
		return sesionRepository.findByName(name);
	}

	public Sesion findByUserAndName(String user, String name) {
		return sesionRepository.findByUserAndName(user, name);
	}

	/**
	 * Do the match and saves the expression and the result in a buffer 
	 * @param user
	 * @param expression
	 * @return
	 * @throws UnknownFunctionException
	 * @throws UnparsableExpressionException
	 */
	public Double calculate(String user, String expression)
			throws UnknownFunctionException, UnparsableExpressionException {
		Calculable calc = null;
		calc = new ExpressionBuilder(expression).build();
		Double result = calc.calculate();
		List<Calculo> userBuffer = buffer.get(user);
		if (userBuffer == null) {
			userBuffer = new ArrayList<Calculo>();
		}
		userBuffer.add(new Calculo(expression + "=" + result));
		buffer.put(user, userBuffer);
		return result;
	}

}
